package org.groupg;

import cn.hutool.core.util.StrUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.groupg.model.ExcelCreateCellData;
import org.groupg.model.ExcelCreateRowData;
import org.groupg.utils.CreateStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 为 Excel 填充数据使用的方法
 */
public class ExcelCreateData {

    /**
     * 树 的key 以及 自定义 的 表名称/别名
     */
    private String index = "";
    /**
     * 树的名称
     */
    private String name = "";

    public String getIndex() {
        return index;
    }

    public void setIndex(String index) {
        this.index = index;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    static final Logger log = LoggerFactory.getLogger(ExcelCreateData.class);
    static final Map<String, SimpleDateFormat> dateFormats = new HashMap<>();
    /**
     * //    {
     * //        colNums.put(1,"constant:STRING:01-账面价值法");
     * //        colNums.put(3,"constant:STRING:12312312314");
     * //        colNums.put(2,"bigint:STRING:唯一性验证标识:%06d");
     * //        colNums.put(0,"RegEx:STRING:[\\u4e00-\\u9fa5]{6,8}[a-z|A-Z]{6,8}[1-9]([0-9]{4,10})");
     * //        colNums.put(5,"constant:STRING:2023-11-08");
     * //    }
     */
    private final Map<Integer, String> colNums = new HashMap<>();
    private ExcelCreateRowData rowData = null;

    public void setRowData(ExcelCreateRowData rowData) {
        this.rowData = rowData;
    }

    public void setColNums(List<ExcelCreateCellData> colNums) {
        for (ExcelCreateCellData data : colNums) {
            this.colNums.put(data.cellIndex(), StrUtil.format("{}:{}:{}:{}", data.createDataType(), data.cellType(), data.cellMode(), data.cellFormat()));
        }
    }

    /**
     * 根据 提供的 Excel 以及 行处理模式，初始化表格数据
     *
     * @param workbook 被处理的 Excel 文件
     * @param rowData  行数据
     * @throws IOException          文件读写相关异常
     * @throws InterruptedException 正则表达式生成字符串异常
     * @throws ParseException       格式化异常
     */
    private void createRowCell(Workbook workbook, ExcelCreateRowData rowData) throws IOException, ParseException, InterruptedException {

        log.debug("参数：sheetName={} startRowNum:{} endRowNum:{} startCellNum:{} endCellNum:{}", rowData.sheetName(), rowData.startRowNum(), rowData.endRowNum(), rowData.startCellNum(), rowData.endCellNum());
        if (workbook == null) throw new NullPointerException("指定的 workbook 参数为空");

        Sheet sheet;
        if (StringUtils.isEmpty(rowData.sheetName())) {
            sheet = workbook.getSheetAt(rowData.sheetIndex());
        } else {
            sheet = workbook.createSheet(rowData.sheetName());
        }
        if (rowData.startRowNum() > rowData.endRowNum() || rowData.startCellNum() > rowData.endCellNum())
            throw new IndexOutOfBoundsException("指定的开始位置大于结束位置，请调整并确认参数！");
        int x = 1;
        for (int rowNum = rowData.startRowNum(); rowNum < rowData.endRowNum(); rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (row == null) {
                row = sheet.createRow(rowNum);
            }
            for (int cellNum = rowData.startCellNum(); cellNum < rowData.endCellNum(); cellNum++) {
                Cell cell = row.getCell(cellNum);
                if (cell == null) {
                    cell = row.createCell(cellNum);
                }
                String cellValue = colNums.get(cellNum);
                if (cellValue == null) {
                    cellValue = "";
                    cell.setCellValue(cellValue);
                } else {
                    String valueType = cellValue.split(":")[0];
                    String cellTypeStr = cellValue.split(":")[1];
                    String valueMode = cellValue.split(":")[2];
                    if ("STRING".equals(cellTypeStr)) {
                        if ("constant".equals(valueType)) {
                            cellValue = valueMode;
                        } else if ("bigint".equals(valueType)) {
                            cellValue = CreateStringUtils.createStrByNumberFormat(valueMode, x);
                        } else if ("RegEx".equals(valueType)) {
                            cellValue = CreateStringUtils.createStrByRegExRandom(valueMode);
                        }
                        cell.setCellValue(cellValue);
                    } else if ("DATE".equals(cellTypeStr)) {
                        String valueFormat = cellValue.split(":")[3];
                        SimpleDateFormat simpleDateFormat = dateFormats.get(valueFormat);
                        if (simpleDateFormat == null) {
                            simpleDateFormat = new SimpleDateFormat(valueFormat);
                            dateFormats.put(valueFormat, simpleDateFormat);
                        }
                        Date date = simpleDateFormat.parse(valueMode);
                        DataFormat format = workbook.createDataFormat();
                        CellStyle style = workbook.getCellStyleAt(cellNum) == null ? workbook.createCellStyle() : workbook.getCellStyleAt(cellNum);
                        style.setDataFormat(format.getFormat(valueFormat));
                        cell.setCellValue(date);
                    }
                }
                x++;
            }
        }
    }

    /**
     * 对外提供的工具方法
     * 调用本方法前需要设置 colNums 与 rowData
     *
     * @param oldFilePath    模板文件地址
     * @param newFilePath    新文件地址
     * @param fileNameFormat 文件名称的格式，可以根据数字进行格式化 类似于 insert_%d.xlsx 后期会生成 insert_0.xlsx insert_1.xlsx insert_2.xlsx
     * @param startNum       启动位置
     * @param endNum         结束位置，控制的时文件名中的 %d 变量范围，可以不从0开始生成。
     * @throws IOException          文件读写相关异常
     * @throws InterruptedException 正则表达式生成字符串异常
     * @throws ParseException       格式化异常
     */
    public void createWorkbook(String oldFilePath, String newFilePath, String fileNameFormat, int startNum, int endNum) throws IOException, InterruptedException, ParseException {

        if (colNums.isEmpty()) {
            log.error("字段属性未设置，请通过 setColNums 方法设置填充字段的属性!");
            throw new NullPointerException("字段属性未设置，请通过 setColNums 方法设置填充字段的属性!");
        }
        if (rowData == null) {
            log.error("字段属性未设置，请通过 setRowData 方法设置填充字段的属性!");
            throw new NullPointerException("字段属性未设置，请通过 setRowData 方法设置填充字段的属性!");
        }
        File newFiles = new File(newFilePath);
        File oldFile = new File(oldFilePath);
        if (!newFiles.isDirectory() || newFiles.exists()) {
            FileUtils.deleteDirectory(newFiles);
            boolean b = newFiles.mkdirs();
            if (!b) {
                log.error("创建文件夹失败，请检查权限是否满足要求！");
                return;
            }
        }
        for (int i = startNum; i < endNum; i++) {
            String fileName = String.format(Locale.CHINA, fileNameFormat, i);
            String aFileName = newFilePath + File.separator + fileName;
            log.debug(aFileName);
            File aFile = new File(aFileName);
            FileUtils.copyFile(oldFile, aFile);
            Workbook workbook = new XSSFWorkbook(Files.newInputStream(aFile.toPath()));
            createRowCell(workbook, this.rowData);
            workbook.write(Files.newOutputStream(aFile.toPath()));
            workbook.close();
        }
    }


}
